/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package cn.ekuma.epos.analysis.product;

import com.openbravo.bean.Location;
import com.openbravo.bean.erp.viewbean.ProductAnalysis;
import com.openbravo.bean.erp.viewbean.ProductTransaction;
import cn.ekuma.epos.analysis.product.model.ProductAnalysisTableModel;
import cn.ekuma.epos.businesslogic.OrderUtil;
import cn.ekuma.epos.datalogic.I_DataLogicERP;
import cn.ekuma.epos.datalogic.I_DataLogicSales;
import com.openbravo.data.basic.BasicException;
import com.openbravo.data.loader.KeyBuilder;
import com.openbravo.data.loader.query.QBFCompareEnum;
import com.openbravo.data.loader.query.QBFParameters;
import com.openbravo.pos.panels.event.LocationChangedListener;
import com.openbravo.pos.panels.event.ProductChangedListener;
import com.openbravo.bean.erp.Order;
import com.openbravo.bean.erp.viewbean.OrderLine_V;
import com.openbravo.bean.erp.OrderType;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.event.EventListenerList;
import net.sourceforge.jtimepiece.TimeUtil;
import org.jfree.data.time.Millisecond;
import org.jfree.data.time.TimeSeries;
import org.jfree.data.time.TimeSeriesCollection;
import org.jfree.data.xy.IntervalXYDataset;
import org.jfree.data.xy.XYDataset;

/**
 *
 * @author Administrator
 */
public class AnalysisModelManager {
    private ArrayList<String> transactionColumns;
    ProductAnalysisTableModel tableModel;
    List<ProductAnalysis> productAnalysis;
    List<ProductTransaction> productTransaction;
    String detailProductID;
    List<OrderType> orderTypes;
    public static String PROPERTY_DialyProductID="detailProductID";
     /** List of listeners */
    protected EventListenerList listenerList = new EventListenerList();
    private TimeSeriesCollection pricetimeSeries;//价格
    private TimeSeriesCollection valueTimeSeries;//数量
    private TimeSeriesCollection storeTimeSeries;//库存变动相对量
    private Map<String,List<OrderLine_V>> orderLineMap;
    private I_DataLogicERP dlSales;
    private Object[] afilter;
    List<OrderLine_V> orderLines;
    private boolean isInclundTransaction;
    

    public AnalysisModelManager(I_DataLogicERP dlSales) {
        this.dlSales=dlSales;
        transactionColumns=new ArrayList<String>();
        tableModel=new ProductAnalysisTableModel();
        pricetimeSeries=new TimeSeriesCollection();
        valueTimeSeries=new TimeSeriesCollection();
        storeTimeSeries=new TimeSeriesCollection();
        orderLineMap=new HashMap<String,List<OrderLine_V>>();
        try {
            orderTypes = dlSales.list(OrderType.class);
        } catch (BasicException ex) {
            Logger.getLogger(AnalysisModelManager.class.getName()).log(Level.SEVERE, null, ex);
        }
        isInclundTransaction=true;
    }

    public void query(Object filter) throws BasicException{
            afilter=(Object[])filter;
            productAnalysis = dlSales.listByFilter(ProductAnalysis.class,new Object[]{afilter[6],afilter[7],afilter[12],afilter[13],afilter[14],afilter[15],afilter[16],afilter[17],afilter[18],afilter[19],afilter[20],afilter[21]});
            if(isInclundTransaction){
              productTransaction =dlSales.productTransactionListQBF(new Object[]{afilter[0],afilter[1],afilter[2],afilter[3],afilter[4],afilter[5],afilter[6],afilter[7],afilter[8],afilter[9],afilter[10],afilter[11],afilter[12],afilter[13],afilter[14],afilter[15],afilter[20],afilter[21]});
              productTransaction.addAll(dlSales.productPOSTransactionListQBF(new Object[]{afilter[0],afilter[1],afilter[2],afilter[3],afilter[4],afilter[5],afilter[6],afilter[7],afilter[10],afilter[11],afilter[12],afilter[13],afilter[14],afilter[15],afilter[20],afilter[21]}));
            }else
            	productTransaction=new ArrayList();
            fillProductTransations();
            tableModel.resert(transactionColumns,productAnalysis);
    }
    
    public void query(String location,String customer,Object filter) throws BasicException{
    	productAnalysis = dlSales.listProductAnalysisByCustomer(location, customer);
    	afilter=(Object[])filter;
    	if(isInclundTransaction){
            productTransaction =dlSales.productTransactionListQBF(new Object[]{afilter[0],afilter[1],afilter[2],afilter[3],afilter[4],afilter[5],afilter[6],afilter[7],afilter[8],afilter[9],afilter[10],afilter[11],afilter[12],afilter[13],afilter[14],afilter[15],afilter[20],afilter[21]});
            productTransaction.addAll(dlSales.productPOSTransactionListQBF(new Object[]{afilter[0],afilter[1],afilter[2],afilter[3],afilter[4],afilter[5],afilter[6],afilter[7],afilter[10],afilter[11],afilter[12],afilter[13],afilter[14],afilter[15],afilter[20],afilter[21]}));
          }else
          	productTransaction=new ArrayList();
          fillProductTransations();
    	tableModel.resert(transactionColumns,productAnalysis);
    }
    

    //算法应改进
    private void fillProductTransations(){
            transactionColumns.clear();
            String realOrderName;
            for(ProductTransaction pt:productTransaction){
              realOrderName=pt.getOrderTypeName()+"("+(pt.getOrderType()==0?OrderUtil.ORDERTYPE_Normal:OrderUtil.ORDERTYPE_Revoerse)+")";
              if(!transactionColumns.contains(realOrderName))
                    transactionColumns.add(realOrderName);
                 for(ProductAnalysis pa:productAnalysis){
                    if(pt.getProductId().equalsIgnoreCase(pa.getM_ID()))
                        pa.putTransaxtion(realOrderName, pt);
                }
        }
    }

    public void initChartModel(String productId) throws BasicException{
        orderLineMap.clear();
        Object[] filter=afilter.clone();
        filter[12]=QBFCompareEnum.COMP_IN;
        filter[13]=new String[]{productId};

            orderLines = dlSales.productTransactionDialyListQBF(filter);
            orderLines.addAll(dlSales.productPOSTransactionDialyListQBF(new Object[]{filter[0],filter[1],filter[2],filter[3],filter[4],filter[5],filter[6],filter[7],filter[10],filter[11],filter[12],filter[13],filter[14],filter[15]}));
            Collections.sort(orderLines,new Comparator(){
                public int compare(Object o1, Object o2) {
                    OrderLine_V line1=(OrderLine_V)o1;
                    OrderLine_V line2=(OrderLine_V)o1;
                    if(TimeUtil.isAfter(line1.getDate(), line2.getDate()))
                        return 1;
                    return 0;
                }
                
            });
        if(orderLines!=null){
            String realOrderName;
            for(OrderLine_V line:orderLines){
                realOrderName=line.getDefineType()+"("+(line.getOrdertype()==0?OrderUtil.ORDERTYPE_Normal:OrderUtil.ORDERTYPE_Revoerse)+")";
                if(!orderLineMap.containsKey(realOrderName)){ 
                    orderLineMap.put(realOrderName, new ArrayList<OrderLine_V>());
                }
                orderLineMap.get(realOrderName).add(line);
            }
        }
        createPriceDataset();
        createVolumeDataset(getTransactionColumns().size()>0?getTransactionColumns().get(0):null);
        createStoreDataset();
    }



    public ArrayList<String> getTransactionColumns() {
        return transactionColumns;
    }

    public TimeSeriesCollection getPricetimeSeries() {
        return pricetimeSeries;
    }

    public TimeSeriesCollection getStoreTimeSeries() {
        return storeTimeSeries;
    }

    public TimeSeriesCollection getValueTimeSeries() {
        return valueTimeSeries;
    }
    
    public XYDataset createPriceDataset(){
          pricetimeSeries.removeAllSeries();
          for(String orderType:orderLineMap.keySet()){
              TimeSeries orderTypeTimeSerie=new TimeSeries(orderType, Millisecond.class);
              List<OrderLine_V> lines=orderLineMap.get(orderType);
              for(OrderLine_V line:lines)
                  orderTypeTimeSerie.add(new Millisecond(line.getDate()),line.getPrice());
              pricetimeSeries.addSeries(orderTypeTimeSerie);
          }
        return pricetimeSeries;
    }

    public IntervalXYDataset createVolumeDataset(String orderType){
       valueTimeSeries.removeAllSeries();
       if(orderType!=null&&orderLineMap.get(orderType)!=null){
            TimeSeries volumeTimeSerie=new TimeSeries(orderType, Millisecond.class);
              for(OrderLine_V line:orderLineMap.get(orderType))
                  volumeTimeSerie.add(new Millisecond(line.getDate()),line.getMultiply());
             valueTimeSeries.addSeries(volumeTimeSerie);
         }
      return valueTimeSeries;
    }

    public XYDataset createStoreDataset(){
          storeTimeSeries.removeAllSeries();
          TimeSeries storeTimeSerie=new TimeSeries("", Millisecond.class);
          double realStore=0;
          for(OrderLine_V l:orderLines){
                  OrderType oType=getOrderTypeByName(l.getDefineType());
                  if(oType.isStoreChanged()){
                      double multipy = l.getMultiply();
                      if (OrderType.STORE_In == oType.getInOutType()&&Order.ORDERBEARING_REVERSE == l.getOrdertype()) {
                                multipy = -multipy;
                        } else if (OrderType.STORE_Out == oType.getInOutType()&&Order.ORDERBEARING_NORMAL == l.getOrdertype()) {
                                multipy = -multipy;
                        } else if (OrderType.STORE_BalanceIn == oType.getInOutType()) {
                            multipy = multipy - l.getConsulMultiply();
                        } else if (OrderType.STORE_BalanceOut == oType.getInOutType()) {
                            multipy = l.getConsulMultiply() - multipy;
                        }
                      realStore+=multipy;
                      storeTimeSerie.add(new Millisecond(l.getDate()),realStore);
                  }
         }
        storeTimeSeries.addSeries(storeTimeSerie);
        return storeTimeSeries;
    }

    public List<OrderLine_V> getOrderLineByOrderType(String orderType){
        return orderLineMap.get(orderType);
    }

    private OrderType getOrderTypeByName(String name){
        if(OrderUtil.ORDERTYPE_POS.getName().equalsIgnoreCase(name))
             return OrderUtil.ORDERTYPE_POS;
        for(OrderType type:orderTypes)
            if(type.getName().equalsIgnoreCase(name))
             return type;
        return null;
    }

    
    public void addProductChangedListener(ProductChangedListener l){
        listenerList.add(ProductChangedListener.class, l);
    }

    public void removeProductChangeListener(ProductChangedListener l){
       listenerList.remove(ProductChangedListener.class, l);
   }

    public ProductChangedListener[] getProductChangedListeners() {
        return (ProductChangedListener[])listenerList.getListeners(ProductChangedListener.class);
    }

    public void fireProductChanged(String id,Object o) {
	// Guaranteed to return a non-null array
	Object[] listeners = listenerList.getListenerList();
	// Process the listeners last to first, notifying
	// those that are interested in this event
	for (int i = listeners.length-2; i>=0; i-=2) {
	    if (listeners[i]==ProductChangedListener.class) {
		((ProductChangedListener)listeners[i+1]).baseBeanChanged(KeyBuilder.getKey(id),null);
	}
      }
    }
    
    

    public void addPropertyChangeListener(PropertyChangeListener l){
        listenerList.add(PropertyChangeListener.class, l);
    }

    public void removePropertyChangeListener(PropertyChangeListener l){
        listenerList.remove(PropertyChangeListener.class, l);
    }

    public void fireDialyProductPropertyChanged(String name,String id,String productName) {
	// Guaranteed to return a non-null array
	Object[] listeners = listenerList.getListenerList();
	// Process the listeners last to first, notifying
	// those that are interested in this event
	for (int i = listeners.length-2; i>=0; i-=2) {
	    if (listeners[i]==PropertyChangeListener.class) {
		((PropertyChangeListener)listeners[i+1]).propertyChange(new PropertyChangeEvent(this,PROPERTY_DialyProductID,detailProductID,new String[]{id,productName}));
	}
      }
      detailProductID=id;
    }

    public I_DataLogicSales getDlSales() {
        return dlSales;
    }
    
    public void addLocationChangedListener(LocationChangedListener l){
		listenerList.add(LocationChangedListener.class, l);
	}
	
	public void removeLocationChangedListener(LocationChangedListener l){
		listenerList.remove(LocationChangedListener.class, l);
	}
	
	public void fireLocationChanged(Location l){
		for(LocationChangedListener list:listenerList.getListeners(LocationChangedListener.class)){
			list.valueSelectChanged(l);
		}
	}

	public boolean isInclundTransaction() {
		return isInclundTransaction;
	}

	public void setInclundTransaction(boolean isInclundTransaction) {
		this.isInclundTransaction = isInclundTransaction;
	}

	public void query(Date startDate, Date endDate, Object[] filter)throws BasicException {
		productAnalysis = dlSales.listProductAnalysisByProductCurDate(startDate, endDate);
    	afilter=(Object[])filter;
    	if(isInclundTransaction){
            productTransaction =dlSales.productTransactionListQBF(new Object[]{afilter[0],afilter[1],afilter[2],afilter[3],afilter[4],afilter[5],afilter[6],afilter[7],afilter[8],afilter[9],afilter[10],afilter[11],afilter[12],afilter[13],afilter[14],afilter[15],afilter[20],afilter[21]});
            productTransaction.addAll(dlSales.productPOSTransactionListQBF(new Object[]{afilter[0],afilter[1],afilter[2],afilter[3],afilter[4],afilter[5],afilter[6],afilter[7],afilter[10],afilter[11],afilter[12],afilter[13],afilter[14],afilter[15],afilter[20],afilter[21]}));
          }else
          	productTransaction=new ArrayList();
          fillProductTransations();
    	tableModel.resert(transactionColumns,productAnalysis);
	}

	public void query(QBFParameters paras) throws BasicException {
		productAnalysis = dlSales.listByFilter(ProductAnalysis.class,paras);
        productTransaction=new ArrayList();
        fillProductTransations();
        tableModel.resert(transactionColumns,productAnalysis);
	}
}
